package com.guangli.data.util

import android.graphics.Canvas
import android.graphics.Path
import android.graphics.RectF
import com.kmdd.xtds.util.HeartBarBuffer
import com.kmdd.xtds.util.HeartBarChartRenderer
import com.github.mikephil.charting.animation.ChartAnimator
import com.github.mikephil.charting.data.BarData
import com.github.mikephil.charting.data.BarEntry
import com.github.mikephil.charting.highlight.Highlight
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet
import com.github.mikephil.charting.utils.Transformer
import com.github.mikephil.charting.utils.Utils
import com.github.mikephil.charting.utils.ViewPortHandler
import kotlin.math.ceil

class HeartCustomBarChartRender(
    chart: BarDataProvider?,
    animator: ChartAnimator?,
    viewPortHandler: ViewPortHandler?
) :
    HeartBarChartRenderer(chart, animator, viewPortHandler) {
    private val mBarShadowRectBuffer: RectF = RectF()
    private var mRadius = 0f
    private var mColorList = mutableListOf<Int>()
    fun setRadius(mRadius: Float) {
        this.mRadius = mRadius
    }

    protected override fun drawDataSet(c: Canvas, dataSet: IBarDataSet, index: Int) {
        val trans: Transformer = mChart.getTransformer(dataSet.axisDependency)
        mBarBorderPaint.color = dataSet.barBorderColor
        mBarBorderPaint.strokeWidth = Utils.convertDpToPixel(dataSet.barBorderWidth)
        mShadowPaint.color = dataSet.barShadowColor
        val drawBorder: Boolean = dataSet.barBorderWidth > 0f
        val phaseX: Float = mAnimator.phaseX
        val phaseY: Float = mAnimator.phaseY
        val path2 = Path()
        val path3 = Path()
        val radii =
            floatArrayOf(mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius)
        if (mChart.isDrawBarShadowEnabled) {
            mShadowPaint.color = dataSet.barShadowColor
            val barData: BarData = mChart.barData
            val barWidth: Float = barData.barWidth
            val barWidthHalf = barWidth / 2.0f
            var x: Float
            var i = 0
            val count = ceil((dataSet.entryCount.toFloat() * phaseX).toDouble()).toInt()
                .coerceAtMost(dataSet.entryCount)
            while (i < count) {
                val e: BarEntry = dataSet.getEntryForIndex(i)
                x = e.x
                mBarShadowRectBuffer.left = x - barWidthHalf
                mBarShadowRectBuffer.right = x + barWidthHalf
                trans.rectValueToPixel(mBarShadowRectBuffer)
                if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right)) {
                    i++
                    continue
                }
                if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left)) break
                mBarShadowRectBuffer.top = mViewPortHandler.contentTop()
                mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom()
//                c.drawRoundRect(mBarRect, mRadius, mRadius, mShadowPaint)
                path3.addRoundRect(mBarShadowRectBuffer, radii, Path.Direction.CW)

                c.drawPath(path3, mShadowPaint)
                i++
            }
        }

        // initialize the buffer
        val buffer: HeartBarBuffer = mBarBuffers.get(index)
        buffer.setPhases(phaseX, phaseY)
        buffer.setDataSet(index)
        buffer.setInverted(mChart.isInverted(dataSet.axisDependency))
        buffer.setBarWidth(mChart.barData.barWidth)
        buffer.feed(dataSet)
        trans.pointValuesToPixel(buffer.buffer)
        val isSingleColor = dataSet.colors.size === 1
        if (isSingleColor) {
            mRenderPaint.color = dataSet.color
        }
        var j = 0
        var colorIndex = 0;
        while (j < buffer.size()) {
            if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) {
                j += 4
                continue
            }
            if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) break
            if (!isSingleColor) {
                // Set the color for the currently drawn value. If the index
                // is out of bounds, reuse colors.
                mRenderPaint.color = dataSet.getColors().get(j / 4)

            }

            val rectF = RectF(
                buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                buffer.buffer[j + 3]
            )
//            val path2: Path = roundRect(
//                rectF , mRadius.toFloat(), mRadius.toFloat(), true, true, false, false
//            )
            //                c.drawRoundRect(rectF,25f, 25f,mRenderPaint);


            c.drawRoundRect(rectF, 50f, 50f, mRenderPaint)
            //c.drawPath(path2, mRenderPaint)

            if (drawBorder) {
                val path: Path = roundRect(
                    RectF(
                        buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                        buffer.buffer[j + 3]
                    ), mRadius, mRadius, tl = true, tr = true, br = false, bl = false
                )
                c.drawPath(path, mBarBorderPaint)
            }
            j += 4
            colorIndex++
        }
    }

    private fun roundRect(
        rect: RectF,
        rx: Float,
        ry: Float,
        tl: Boolean,
        tr: Boolean,
        br: Boolean,
        bl: Boolean
    ): Path {
        var rx = rx
        var ry = ry
        val top: Float = rect.top
        val left: Float = rect.left
        val right: Float = rect.right
        val bottom: Float = rect.bottom
        val path = Path()
        if (rx < 0) rx = 0f
        if (ry < 0) ry = 0f
        val width = right - left
        val height = bottom - top
        if (rx > width / 2) rx = width / 2
        if (ry > height / 2) ry = height / 2
        val widthMinusCorners = width - 2 * rx
        val heightMinusCorners = height - 2 * ry
        path.moveTo(right, top + ry)
        if (tr) path.rQuadTo(0f, -ry, -rx, -ry) //top-right corner
        else {
            path.rLineTo(0f, -ry)
            path.rLineTo(-rx, 0f)
        }
        path.rLineTo(-widthMinusCorners, 0f)
        if (tl) path.rQuadTo(-rx, 0f, -rx, ry) //top-left corner
        else {
            path.rLineTo(-rx, 0f)
            path.rLineTo(0f, ry)
        }
        path.rLineTo(0f, heightMinusCorners)
        if (bl) path.rQuadTo(0f, ry, rx, ry) //bottom-left corner
        else {
            path.rLineTo(0f, ry)
            path.rLineTo(rx, 0f)
        }
        path.rLineTo(widthMinusCorners, 0f)
        if (br) path.rQuadTo(rx, 0f, rx, -ry) //bottom-right corner
        else {
            path.rLineTo(rx, 0f)
            path.rLineTo(0f, -ry)
        }
        path.rLineTo(0f, -heightMinusCorners)
        path.close() //Given close, last lineto can be removed.
        return path
    }

    override fun drawHighlighted(c: Canvas, indices: Array<Highlight>) {
        val barData = mChart.barData
        val path2 = Path()
        val path = Path()
        val radii =
            floatArrayOf(mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius, mRadius)
        for (high in indices) {
            val set = barData.getDataSetByIndex(high.dataSetIndex)
            if (set == null || !set.isHighlightEnabled) continue
            val e = set.getEntryForXValue(high.x, high.y)
            if (!isInBoundsX(e, set)) continue
            val trans = mChart.getTransformer(set.axisDependency)
            mHighlightPaint.color = set.highLightColor
            mHighlightPaint.alpha = set.highLightAlpha
            val isStack = high.stackIndex >= 0 && e.isStacked
            val y1: Float
            val y2: Float
            if (isStack) {
                if (mChart.isHighlightFullBarEnabled) {
                    y1 = e.positiveSum
                    y2 = -e.negativeSum
                } else {
                    val range = e.ranges[high.stackIndex]
                    y1 = range.from
                    y2 = range.to
                }
            } else {
                y1 = e.y//mBarShadowRectBuffer.bottom//e.y
                y2 = 0f
            }

            prepareBarHighlight(e.x, y1, y2, barData.barWidth / 2f, trans)
            setHighlightDrawPos(high, mBarRect)
            val rectF1 = RectF(
                mBarRect.left, mBarShadowRectBuffer.top, mBarRect.right,
                mBarRect.bottom
            )


            path2.addRoundRect(rectF1, radii, Path.Direction.CW)
//            LogUtils.e(mBarShadowRectBuffer, mBarRect, e.toString())
            c.drawPath(path2, mHighlightPaint)
//
            path.addRoundRect(mBarRect, radii, Path.Direction.CW)
            c.drawPath(path, mRenderPaint)
//            c.drawCircle(mBarRect.left, mBarRect.bottom, 10f, mRenderPaint)
//            c.drawRect(mBarRect, mHighlightPaint)
        }
    }
}